<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../js/vue.global.js"></script>
</head>

<body>
    <div id="app">
        <p>{{a}}---{{doubleA}}</p>
        <p>
            <button @click="addA">a++</button>
            <button @click="doubleA+=2">doubleA+2</button>
        </p>
        <hr>
        <p>{{zhang.name}}---{{zhang.age}}</p>
        <p>
            <button @click="changeName">changeName</button>
            <button @click="changeAge">changeAge</button>
        </p>
    </div>
</body>
<script>
    // Vue3  => Vue的第三个大版本修改  
    // 相较于Vue2  
    // 1. 选项式语法做了修改  



    // Vue3
    // 1. Vue  => 全局对象  => {createApp,nextTick,ref,reactive}
    // 2. Vue中对象存有创建引用的方法  var {createApp} = Vue;
    // 3. Vue3的选项式语法中 没有el属性 => 通过app.mount() 指定挂载的元素
    // 4. Vue3的选项式语法中 data是一个返回对象的函数  => 所有的组件均是如此 
    // 5. Vue3中 data methods computed 不在存储在Vue组件(实例)上  => 而是单独存储到一个对象上(代理对象 proxy)  =>  方法中的this默认都指向代理对象  => 取值和赋值都通过代理对象执行
    // 6. Vue3中 全局属性 组件 指令 插件 都是依赖于app定义的

    // 组合式语法

    console.log(Vue);

    var { createApp } = Vue;
    var { ref, reactive, readonly, computed } = Vue;
    var app = createApp({
        // 组合式
        setup: function (props) {
            console.log("setup钩子函数开始执行");
            // props  在组件通信过程中,用于接收父组件传入数据的属性
            // 在组合式语法中 可以定义数据(data) methods, 计算属性, 绑定监听, 绑定生命周期钩子函数 => 完成选项式相同的效果  
            // 组合式语法中抛弃了this =>直接对应数据修改

            // 如何定义数据?



            // 定义普通变量  => 问题: Vue无法监听变量的值发生改变 => 不会更新视图
            // var a = 10;
            // function addA(){
            //     a++;
            //     console.log(1111,a);
            // }

            // ref  => 可以创建一个对数值的引用
            // 1. 调用此方法会返回一个ref对象传入的值会作为value属性的默认值)
            // 2. ref对象中存在value属性(传入的值会作为value属性的默认值),ref对象上的value属性上配置了getter setter(取值拦截和赋值拦截)   => ref对象取value值会触发取值拦击  对ref对象的value属性赋值时会触发赋值拦截 => Vue响应式检测到
            // 3. Vue会默认对setup函数中返回ref对象进行解包 => 


            // reactive()  => 创建一个对对象的引用=>返回的是proxy对象/响应对象
            // 操作proxy对象(取值/赋值) => 会同步更新到源对象 

            // readonly()  接受一个对象 (不论是响应式还是普通的) 或是一个 ref，返回一个原值的只读代理。  =>只能取值, 不能赋值

            var a = ref(10); // {value:10}
            // console.log("ref",a);
            // console.log("ref",a.value);

            var zhang = reactive({ name: "张飒", age: 18 }); // new Proxy(target,{get,set})
            // console.log("reactive",zhang);
            // console.log("proxy取值",zhang.name);
            // console.log("proxy取值",zhang.age);


            // 计算属性  => 本质也是一个ref对象
            // 1. 此写法默认只有取值,没有赋值 => 也是只读的
            // var doubleA = computed(()=>{
            //     return a.value * 2;
            // })

            // 2. 给计算属性设置了 getter  setter => 取值拦截和赋值拦截
            var doubleA = computed({
                get: () => {
                    console.log("计算属性doubleA取值");
                    return a.value * 2;
                },
                set: (val) => {
                    console.log("计算属性doubleA赋值");
                    a.value = val / 2
                }
            })
            console.log("doubleA", doubleA);


            // 定义方法 methods
            function addA() {
                a.value++;
            }

            function changeName() {
                zhang.name = '李四'
            }
            function changeAge() {
                zhang.age++
            }





            // 闭包  => setup函数中返回的数据/计算属性/方法/监听  就是后面选项式语法中接收的
            // 对象中的键名 => 后面选项式语法中proxy代理对象中的属性名
            // 对象中的键值 => setup函数中的对象 方法
            return {
                a: a, // a:ref对象
                zhang: zhang, // zhang:proxy对象(zhang)
                doubleA: doubleA,
                addA: addA,
                changeName: changeName,
                changeAge: changeAge,
            }
        },
        // 选项式
        // data(){},
        // computed:{},
        // methods:{},
        // watch:{},

        beforeCreate() {
            console.log("beforeCreate", this);
            // console.log("beforeCreate",this.a);  // proxy对象取值是进行了解包  this.a => ref.value;

            // this.a = 100;   // ref.value = 100;
            // console.log("beforeCreate",this.a); // this.a => ref.value;

        },

        created() {
            console.log("created", this);
        },
        // mounted() {
        //     console.log("组件挂载完毕",this);
        // },
    })

    console.log("app", app);
    app.mount("#app");




</script>



</html>